#include <iostream>
#include <vector>
using namespace std;

class Main {
	using vec = vector<int>;
	using vec2 = vector<vec>;
	using vec3 = vector<vec2>;
	const int MOD = 100000000;
	int N = 0, M = 0, maxs = 0;
	vec2 grid;

	int get(int s, int j)
	{
		return (s >> j) & 1;
	}

	int set(int s, int j, int v)
	{
		return v == 0 ? (s & (~(1 << j))) : (s | (1 << j));
	}

    public:
	Main(int n, int m) : N(n), M(m), grid(n + 2, vec(m + 2, 0))
	{
		maxs = 1 << M;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				cin >> grid[i][j];
			}
		}
	}

	int method3()
	{
		vector<int> dp(1 << M, 1);
		vector<int> new_dp(1 << M, 0);

		for(int i = N - 1; i >= 0; i--){
			for(int j = M - 1; j >= 0; j--){
				for(int s = 0; s < (1 << M); s++){
					int left = j == 0 ? 0 : get(s, j - 1);
					int top = get(s, j);
					int ans = dp[set(s, j, 0)];
					if(grid[i][j] == 1 && left == 0 && top == 0){
						ans = (ans + dp[set(s, j, 1)])%MOD;
					}
					new_dp[s] = ans;
				}
				dp.swap(new_dp);
			}
		}
		return dp[0];
	}

	int method2()
	{
		// vector<int> dp(1 << M, 0);
		// vector<int> new_dp(1 << M, 0);
		// dp[0] = 1;
		vec2 dp(M + 1, vec(1 << M, 0));
		dp[0][0] = 1;

		for (int i = 0; i <= N; i++) {
			for (int j = 0; j < M; j++) {
				fill(dp[j + 1].begin(), dp[j + 1].end(), 0);
				for (int s = 0; s < (1 << M); s++) {
					if (dp[j][s] == 0) {
						continue;
					}

					int left = j == 0 ? 0 : get(s, j - 1);
					int top = get(s, j);
					dp[j + 1][set(s, j, 0)] += dp[j][s];
					dp[j + 1][set(s, j, 0)] %= MOD;
					if (grid[i][j] == 1 && left == 0 && top == 0) {
						dp[j + 1][set(s, j, 1)] += dp[j][s];
						dp[j + 1][set(s, j, 1)] %= MOD;
					}
				}
				//dp.swap(new_dp);
			}
			dp[0].swap(dp[M]);
		}
		return dp[0][0];
	}

	int method()
	{
		vector<int> dp(1 << M, 0);
		vector<int> new_dp(1 << M, 0);
		dp[0] = 1;

		for (int i = 0; i <= N; i++) {
			for (int j = 0; j < M; j++) {
				for (int s = 0; s < (1 << M); s++) {
					if (dp[s] == 0) {
						continue;
					}

					// if (grid[i][j] == 0) {
					// 	new_dp[set(s, j, 0)] += dp[s];
					// 	new_dp[set(s, j, 0)] %= MOD;
					// } else {
					// 	int left = j == 0 ? 0 : get(s, j - 1);
					// 	int top = get(s, j);
					// 	new_dp[set(s, j, 0)] += dp[s];
					// 	new_dp[set(s, j, 0)] %= MOD;
					// 	if (left == 0 && top == 0) {
					// 		new_dp[set(s, j, 1)] += dp[s];
					// 		new_dp[set(s, j, 1)] %= MOD;
					// 	}
					// }

					int left = j == 0 ? 0 : get(s, j - 1);
					int top = get(s, j);
					new_dp[set(s, j, 0)] += dp[s];
					new_dp[set(s, j, 0)] %= MOD;
					if (grid[i][j] == 1 && left == 0 && top == 0) {
						new_dp[set(s, j, 1)] += dp[s];
						new_dp[set(s, j, 1)] %= MOD;
					}
				}
				dp.swap(new_dp);
				fill(new_dp.begin(), new_dp.end(), 0);
			}
		}
		return dp[0];
	}

	int method(int i, int j, int s, vec3 &dp)
	{
		if (i == N) {
			return 1;
		}

		if (j == M) {
			return method(i + 1, 0, s, dp);
		}

		if (dp[i][j][s] != -1) {
			return dp[i][j][s];
		}

		int top = get(s, j);
		int left = j == 0 ? 0 : get(s, j - 1);

		int ans = 0;
		// if (grid[i][j] == 0) {
		// 	ans = method(i, j + 1, set(s, j, 0), dp);
		// } else {
		// 	ans = method(i, j + 1, set(s, j, 0), dp);
		// 	if (top == 0 && left == 0) {
		// 		ans = (ans + method(i, j + 1, set(s, j, 1), dp)) % MOD;
		// 	}
		// }

		ans = method(i, j + 1, set(s, j, 0), dp);
		if (grid[i][j] == 1 && top == 0 && left == 0) {
			ans = (ans + method(i, j + 1, set(s, j, 1), dp)) % MOD;
		}

		return dp[i][j][s] = ans;
	}
};

int main()
{
	int n, m;
	cin >> n >> m;
	Main app(n, m);
	vector<vector<vector<int>>> dp(n + 2, vector<vector<int>>(m + 2, vector<int>(1 << m, -1)));
	cout << app.method(0, 0, 0, dp) << endl;
	cout << app.method() << endl;
	cout << app.method3() << endl;
	return 0;
}

/*

1 3
1 1 1

*/